Skip to content

feat: Add braintrust/apply-instrumentation entrypoint for CJS/TS patching#2038

Open
Luca Forstner (lforst) wants to merge 4 commits into
mainfrom
lforst/apply-instrumentation
Open

feat: Add braintrust/apply-instrumentation entrypoint for CJS/TS patching#2038
Luca Forstner (lforst) wants to merge 4 commits into
mainfrom
lforst/apply-instrumentation

Conversation

@lforst
Copy link
Copy Markdown
Member

@lforst Luca Forstner (lforst) commented May 21, 2026

We have the problem that we don't have a good setup story around frameworks like Nestjs that are CJS but don't give you a clean way of passing the --import hook. For this I thought we could expose something like import 'braintrust/apply-instrumentation' which is simply an import with a side effect that applies runtime patching. It's also good for platforms like Vercel where passing the --import argument is super painful in general.

This will now be usable with

  • CJS doing require('braintrust/apply-instrumentation') for all subsequent requires
  • ESM doing import 'braintrust/apply-instrumentation' for all subsequent dynamic imports (import('foobar').then(() => console.log('foobar is instrumented')))

initLogger can be called whenever.

Currently we only expose this for Nodejs - I haven't looked into how to make this work for other frameworks. I generally like the ergonomics of this and it is an additional tool in our toolbox of doing instrumentation.

…ntation

# Conflicts:
#	js/src/auto-instrumentations/configs/all.ts
#	js/src/instrumentation/braintrust-plugin.ts
#	js/src/instrumentation/registry.ts
"braintrust": minor
---

feat: Add `braintrust/apply-instrumentation` entrypoint for CJS/TS patching
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we call it braintrust/apply-auto-instrumentation instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can!

Copy link
Copy Markdown
Collaborator

@Qard Stephen Belanger (Qard) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will likely be fairly unreliable. The reason we use --import rather than a first import is that import execution order is non-deterministic. It does not happen by order of appearance in the graph, it happens by load completion order.

ESM will load all imports in parallel recursively and will execute in the order in which modules complete loading and either have their dependencies already executed or have no dependencies. So it runs from the leaf nodes in load completion order and makes its way back to the root. This means that by the time it gets back to the entrypoint root node a later import in that file could be fully resolved before an earlier one depending on which was able to load its sub-graph faster.

With --import it will fully resolve the sub-graph of that file before beginning the resolve of the entrypoint file.

I won't block landing this because it might work for some users, but we should be aware that the ordering of this will be inconsistent and may result in users complaining about some imports not getting patched sometimes.

@lforst
Copy link
Copy Markdown
Member Author

This will likely be fairly unreliable. The reason we use --import rather than a first import is that import execution order is non-deterministic. It does not happen by order of appearance in the graph, it happens by load completion order.

Afaik yes, but this is not what I care about with this PR. IIRC applying the esm hooks before doing a dynamic import as I've outlined in the PR will always apply the hooks to the dynamically imported module. I was going for solving the dynamic imports case and the require() case.

I do not think there currently is a solution to patching "normal" imports via normal runtime code.

@Qard
Copy link
Copy Markdown
Collaborator

Ah, yes, a dynamic import graph resolution will happen later, so that could be fine. 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants